package gui;

import io.Carpeta;
import io.Cliente;
import io.servicios.InterfazServiciosServidor;
import io.servicios.ServiciosServidorException;
import java.awt.Component;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.JTabbedPane;
import logica.Nucleo;
import logica.VerificadorException;

/**
 *
 * @author Mariano Zapata
 */
public class PanelPestaniasControlador {

    private Ventana ventana;
    private PanelArbolControlador pac;
    private Nucleo nucleo;
    private JTabbedPane panelPestanias;

    public PanelPestaniasControlador(JTabbedPane panelPestanias)
    {
        this.panelPestanias= panelPestanias;
        ventana= null;
        pac= null;
        nucleo= null;
    }

    public void setVentana(Ventana v) {
        ventana= v;
    }

    public void setPanelArbolControlador(PanelArbolControlador pac) {
        this.pac= pac;
    }

    public void setNucleo(Nucleo n) {
        nucleo= n;
    }

    public void abrirExpediente(Carpeta expediente)
    {
        int indice= panelPestanias.getTabCount();
        for (int k= 0; k < indice; k++)
        {
            Component componente= panelPestanias.getComponentAt(k);
            if (componente instanceof PanelExpediente && ((PanelExpediente) componente).getExpediente().equals(expediente))
            {
                panelPestanias.setSelectedIndex(k);
                return;
            }
        }
        try {
            nucleo.setSistemaOcupado();
            Carpeta expedienteAbierto= nucleo.abrirExpediente(expediente);
            RenderPestania rp= new RenderPestania();
            PanelExpediente pe= new PanelExpediente(expedienteAbierto, rp, this);
            rp.setPanel(pe);
            panelPestanias.insertTab(null, null, pe, null, indice);
            panelPestanias.setTabComponentAt(indice, rp);
            panelPestanias.setSelectedIndex(indice);
            nucleo.setSistemaLibre();
        } catch (RemoteException ex) {this.manejarExcepcion(ex, expediente.getNombre(), "expediente");}
    }

    public void abrirCliente(Cliente c)
    {
        int indice= panelPestanias.getTabCount();
        for (int k= 0; k < indice; k++)
        {
            Component componente= panelPestanias.getComponentAt(k);
            if (componente instanceof PanelCliente && ((PanelCliente) componente).getCliente().equals(c))
            {
                panelPestanias.setSelectedIndex(k);
                return;
            }
        }
        try {
            nucleo.setSistemaOcupado();
            Cliente clienteAbierto= nucleo.abrirCliente(c);
            RenderPestania rp= new RenderPestania();
            PanelCliente pc= new PanelCliente(clienteAbierto, rp, this);
            rp.setPanel(pc);
            panelPestanias.insertTab(null, null, pc, null, indice);
            panelPestanias.setTabComponentAt(indice, rp);
            panelPestanias.setSelectedIndex(indice);
            nucleo.setSistemaLibre();
        } catch (RemoteException ex) {this.manejarExcepcion(ex, c.toString(), "cliente");}
    }

    public void abrirExpedienteNuevo(Carpeta expediente)
    {
        nucleo.setSistemaOcupado();
        RenderPestania rp= new RenderPestania();
        PanelExpediente pe= new PanelExpediente(expediente, rp, this);
        rp.setPanel(pe);
        int pos= panelPestanias.getTabCount();
        panelPestanias.insertTab(null, null, pe, null, pos);
        panelPestanias.setTabComponentAt(pos, rp);
        panelPestanias.setSelectedIndex(pos);
        nucleo.setSistemaLibre();
    }

    public void abrirClienteNuevo(Cliente c)
    {
        nucleo.setSistemaOcupado();
        RenderPestania rp= new RenderPestania();
        PanelCliente pc= new PanelCliente(c, rp, this);
        rp.setPanel(pc);
        int pos= panelPestanias.getTabCount();
        panelPestanias.insertTab(null, null, pc, null, pos);
        panelPestanias.setTabComponentAt(pos, rp);
        panelPestanias.setSelectedIndex(pos);
        nucleo.setSistemaLibre();
    }

    public void cerrarPestaniaExpedienteEliminado(Carpeta expediente)
    {
        int indice= panelPestanias.getTabCount();
        for (int k= 0; k < indice; k++)
        {
            Component componente= panelPestanias.getComponentAt(k);
            if (componente instanceof PanelExpediente && ((PanelExpediente) componente).getExpediente().equals(expediente))
            {
                panelPestanias.removeTabAt(k);
                return;
            }
        }
    }

    public void cerrarPestaniaClienteEliminado(Cliente c)
    {
        int indice= panelPestanias.getTabCount();
        for (int k= 0; k < indice; k++)
        {
            Component componente= panelPestanias.getComponentAt(k);
            if (componente instanceof PanelCliente && ((PanelCliente) componente).getCliente().equals(c))
            {
                panelPestanias.removeTabAt(k);
                return;
            }
        }
    }

    public void cerrarPestaniasExpedientesEliminados(List<Carpeta> lista)
    {
        for (Carpeta car : lista)
            this.cerrarPestaniaExpedienteEliminado(car);
    }

    public void cerrarPestaniasClientesEliminados(List<Cliente> lista)
    {
        for (Cliente cli : lista)
            this.cerrarPestaniaClienteEliminado(cli);
    }

    public void cerrarPestania(PanelExpediente pe)
    {
        try {
            if (pe.estaModificado())
            {
                String msj= "El expediente " + pe.getExpediente().getNombre() + " ha sido modificado.\n" +
                        "¿Desea guardar los cambios?";
                int resp= JOptionPane.showConfirmDialog(ventana, msj, "Guardar expediente",
                        JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
                nucleo.setSistemaOcupado();
                switch (resp)
                {
                    case JOptionPane.YES_OPTION:
                        Carpeta carpeta= nucleo.guardarCarpeta(pe.validar());
                        pe.setGuardado();
                        nucleo.cerrarExpediente(pe.getExpediente());
                        pac.actualizarCarpeta(carpeta, InterfazServiciosServidor.ORDENAR_CARPETAS);
                        break;
                    case JOptionPane.NO_OPTION:
                        nucleo.cerrarExpediente(pe.getExpediente());
                        break;
                    case JOptionPane.CANCEL_OPTION:
                        nucleo.setSistemaLibre();
                        return;
                }
            }
            else
            {
                nucleo.setSistemaOcupado();
                nucleo.cerrarExpediente(pe.getExpediente());
            }
            this.buscarPestaniaYRemover(pe);
            nucleo.setSistemaLibre();
        } catch (VerificadorException ex) {nucleo.setSistemaLibre();
                                           this.errorGuardar(pe.getExpediente().getNombre(), "expediente");}
          catch (RemoteException ex) {ventana.errorRed(ex.getMessage());}
    }

    public void cerrarPestania(PanelCliente pc)
    {
        try {
            if (pc.estaModificado())
            {
                String msj= "El cliente " + pc.getCliente().toString() + " ha sido modificado.\n" +
                        "¿Desea guardar los cambios?";
                int resp= JOptionPane.showConfirmDialog(ventana, msj, "Guardar cliente",
                        JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
                nucleo.setSistemaOcupado();
                switch (resp)
                {
                    case JOptionPane.YES_OPTION:
                        Carpeta carpeta= nucleo.guardarCliente(pc.validar());
                        pc.setGuardado();
                        nucleo.cerrarCliente(pc.getCliente());
                        pac.actualizarCarpeta(carpeta, InterfazServiciosServidor.ORDENAR_CLIENTES);
                        break;
                    case JOptionPane.NO_OPTION:
                        nucleo.cerrarCliente(pc.getCliente());
                        break;
                    case JOptionPane.CANCEL_OPTION:
                        nucleo.setSistemaLibre();
                        return;
                }
            }
            else
            {
                nucleo.setSistemaOcupado();
                nucleo.cerrarCliente(pc.getCliente());
            }
            this.buscarPestaniaYRemover(pc);
            nucleo.setSistemaLibre();
        } catch (VerificadorException ex) {nucleo.setSistemaLibre();
                                           this.errorGuardar(pc.getCliente().toString(), "cliente");}
          catch (RemoteException ex) {ventana.errorRed(ex.getMessage());}
    }

    public List<ItemGuardar> getPanelesExpedienteModificados()
    {
        List<ItemGuardar> ret= new ArrayList<ItemGuardar>();
        int indice= panelPestanias.getTabCount();
        for (int k= 0; k < indice; k++)
        {
            Component actual= panelPestanias.getComponentAt(k);
            if (actual instanceof PanelExpediente && ((PanelExpediente) actual).estaModificado())
                ret.add(new ItemGuardar(actual, true));
        }
        return ret;
    }

    /**
     * Retorna todos los paneles clientes modificados. Si no hay paneles modificados retorna una lista vacía.
     */
    public List<ItemGuardar> getPanelesClientesModificados()
    {
        List<ItemGuardar> ret= new ArrayList<ItemGuardar>();
        int indice= panelPestanias.getTabCount();
        for (int k= 0; k < indice; k++)
        {
            Component actual= panelPestanias.getComponentAt(k);
            if (actual instanceof PanelCliente && ((PanelCliente) actual).estaModificado())
                ret.add(new ItemGuardar(actual, true));
        }
        return ret;
    }

    public void cerrarPestaniasNoModificadas() throws RemoteException
    {
        for (int k= panelPestanias.getTabCount() - 1; k >= 0; k--)
        {
            Component actual= panelPestanias.getComponentAt(k);
            if (actual instanceof PanelExpediente)
            {
                if (!((PanelExpediente) actual).estaModificado())
                {
                    nucleo.cerrarExpediente(((PanelExpediente) actual).getExpediente());
                    panelPestanias.removeTabAt(k);
                }
            }
            else
            {
                if (!((PanelCliente) actual).estaModificado())
                {
                    nucleo.cerrarCliente(((PanelCliente) actual).getCliente());
                    panelPestanias.removeTabAt(k);
                }
            }
        }
    }

    public Carpeta cerrarPestaniaModificada(Component c, boolean guardar) throws VerificadorException, RemoteException
    {
        Carpeta ret= null;
        if (c instanceof PanelExpediente && guardar)
        {
            ret= nucleo.guardarCarpeta(((PanelExpediente) c).validar());
            nucleo.cerrarExpediente(((PanelExpediente) c).getExpediente());
        }
        if (c instanceof PanelCliente && guardar)
        {
            ret= nucleo.guardarCliente(((PanelCliente) c).validar());
            nucleo.cerrarCliente(((PanelCliente) c).getCliente());
        }
        this.buscarPestaniaYRemover(c);
        return ret;
    }

    private void guardarPanelExpediente(PanelExpediente pe) throws VerificadorException, RemoteException
    {
        if (pe.estaModificado())
        {
            nucleo.setSistemaOcupado();
            Carpeta temp= nucleo.guardarCarpeta(pe.validar());
            pe.setGuardado();
            pac.actualizarCarpeta(temp, InterfazServiciosServidor.ORDENAR_CARPETAS);
            nucleo.setSistemaLibre();
        }
    }

    private void guardarPanelCliente(PanelCliente pc) throws VerificadorException, RemoteException
    {
        if (pc.estaModificado())
        {
            nucleo.setSistemaOcupado();
            Carpeta temp= nucleo.guardarCliente(pc.validar());
            pc.setGuardado();
            pac.actualizarCarpeta(temp, InterfazServiciosServidor.ORDENAR_CLIENTES);
            nucleo.setSistemaLibre();
        }
    }

    public void guardarPestaniaSeleccionada()
    {
        Component c= panelPestanias.getSelectedComponent();
        if (c != null)
        {
            if (c instanceof PanelExpediente)
            {
                PanelExpediente pe= (PanelExpediente) c;
                try {
                    this.guardarPanelExpediente(pe);
                } catch (VerificadorException ex) {nucleo.setSistemaLibre();
                                                   this.errorGuardar(pe.getExpediente().getNombre(), "expediente");}
                  catch (RemoteException ex) {ventana.errorRed(ex.getMessage());}
            }
            else
            {
                PanelCliente pc= (PanelCliente) c;
                try {
                    this.guardarPanelCliente(pc);
                } catch (VerificadorException ex) {nucleo.setSistemaLibre();
                                                   this.errorGuardar(pc.getCliente().toString(), "cliente");}
                  catch (RemoteException ex) {ventana.errorRed(ex.getMessage());}
            }
        }
    }

    public void guardarPestaniasTodas()
    {
        boolean huboErrorValidar= false;
        List<Carpeta> tempExp= new ArrayList<Carpeta>();
        List<Carpeta> tempCli= new ArrayList<Carpeta>();
        int indice= panelPestanias.getTabCount();
        try {
            nucleo.setSistemaOcupado();
            for (int k= 0; k < indice; k++)
            {
                Component c= panelPestanias.getComponentAt(k);
                if (c instanceof PanelExpediente)
                {
                    PanelExpediente actual= (PanelExpediente) c;
                    if (actual.estaModificado())
                    {
                        try {
                            Carpeta carpetaActual= nucleo.guardarCarpeta(actual.validar());
                            actual.setGuardado();
                            int pos= tempExp.indexOf(carpetaActual);
                            if (pos >= 0)
                                tempExp.remove(pos);
                            tempExp.add(carpetaActual);
                        } catch (VerificadorException ex) {huboErrorValidar= true;}
                    }
                }
                else
                {
                    PanelCliente actual= (PanelCliente) c;
                    if (actual.estaModificado())
                    {
                        try {
                            Carpeta carpetaActual= nucleo.guardarCliente(actual.validar());
                            actual.setGuardado();
                            int pos= tempCli.indexOf(carpetaActual);
                            if (pos >= 0)
                                tempCli.remove(pos);
                            tempCli.add(carpetaActual);
                        } catch (VerificadorException ex) {huboErrorValidar= true;}
                    }
                }
            }
            for (Carpeta car : tempExp)
                pac.actualizarCarpeta(car, InterfazServiciosServidor.ORDENAR_CARPETAS);
            for (Carpeta car : tempCli)
                pac.actualizarCarpeta(car, InterfazServiciosServidor.ORDENAR_CLIENTES);
            nucleo.setSistemaLibre();
            if (huboErrorValidar)
            {
                String msj= "No se lograron guardar algunos elementos ya que poseen campos incorrectos.";
                JOptionPane.showMessageDialog(ventana, msj, "Guardar todo", JOptionPane.ERROR_MESSAGE);
            }
        } catch (RemoteException ex) {ventana.errorRed(ex.getMessage());}
    }

    private void manejarExcepcion(RemoteException ex, String nombre, String tipo)
    {
        nucleo.setSistemaLibre();
        if (ex.getCause() instanceof ServiciosServidorException)
        {
            String msj= "";
            ServiciosServidorException e= (ServiciosServidorException) ex.getCause();
            switch (e.getCodigo())
            {
                case ServiciosServidorException.ERROR_ELEMENTO_ELIMINADO:
                    msj= "El " + tipo + " " + nombre + " no se puede abrir porque\nha sido eliminado " +
                            "por otro usuario en la red.";
                    break;
                case ServiciosServidorException.ERROR_ELEMENTO_OCUPADO:
                    msj= "El " + tipo + " " + nombre + " no se puede abrir porque\n está siendo " +
                            "utilizado por otro usuario en la red.";
                    break;
            }
            JOptionPane.showMessageDialog(ventana, msj, "Abrir " + tipo, JOptionPane.WARNING_MESSAGE);
        }
        else
            ventana.errorRed(ex.getMessage());
    }

    private void buscarPestaniaYRemover(Component c)
    {
        int indice= panelPestanias.getTabCount();
        for (int k= 0; k < indice; k++)
        {
            if (panelPestanias.getComponentAt(k).equals(c))
            {
                panelPestanias.removeTabAt(k);
                return;
            }
        }
    }

    private void errorGuardar(String nombre, String tipo)
    {
        String msj= "Los cambios en el " + tipo + " " + nombre + " no han sido guardados\nya que posee campos incorrectos.";
        JOptionPane.showMessageDialog(ventana, msj, "Guardar " + tipo, JOptionPane.ERROR_MESSAGE);
    }
}
